<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Other Aspects of the Object Extension
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora145.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora147.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Other Aspects of the Object Extension</H2>In this section we describe the declaration of ``object'' types and
local declarations in classes. The latter can be used for class variables
by making constructors that reference the local environment.<BR>
<BR>
<A NAME="toc215"></A>
<H3> Interfaces</H3><A NAME="@concepts335"></A>
<A NAME="@concepts336"></A>
Class interfaces are generally infered by the type system, but they can also be
defined by a type declaration. Only public methods appear in this type.<BR>
<BR>


<H3> Syntax </H3> <HR>


<TABLE CELLSPACING=2 CELLPADDING=0>
<TR><TD  ALIGN=left NOWRAP><B>class</B> <B>type</B> <I>name</I> =</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>object</B></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;:</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;<B>val</B> <I>name</I><SUB><I><FONT SIZE=2><I>i</I></FONT></I></SUB> <B>:</B> <I>type</I><SUB><I><FONT SIZE=2><I>i</I></FONT></I></SUB></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;:</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;<B>method</B> <I>name</I><SUB><I><FONT SIZE=2><I>j</I></FONT></I></SUB> <B>:</B> <I>type</I><SUB><I><FONT SIZE=2><I>j</I></FONT></I></SUB></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;:</TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>end</B></TD>
</TR></TABLE>



<HR>


Thus we can define the class <TT>point</TT> interface:


<PRE><BR># <B>class</B><CODE> </CODE><B>type</B><CODE> </CODE>interf_point<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_x<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_y<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>moveto<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<CODE> </CODE><TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>rmoveto<CODE> </CODE><CODE>:</CODE><CODE> </CODE><TT>(</TT>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<CODE> </CODE><TT>)</TT><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>to_string<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>string<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>distance<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>float<BR><CODE> </CODE><B>end</B><CODE> </CODE>;;<CODE> </CODE><BR>

</PRE>
<BR>
<BR>
This declaration is useful because the defined type can be
used as a type constraint.


<PRE><BR># <B>let</B><CODE> </CODE>seg_length<CODE> </CODE><TT>(</TT>p1<CODE>:</CODE>interf_point<TT>)</TT><CODE> </CODE><TT>(</TT>p2<CODE>:</CODE>interf_point<TT>)</TT><CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>float_of_int<CODE> </CODE><TT>(</TT>p2#get_x<CODE> </CODE><CODE>-</CODE><CODE> </CODE>p1#get_x<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>float_of_int<CODE> </CODE><TT>(</TT>p2#get_y<CODE> </CODE><CODE>-</CODE><CODE> </CODE>p1#get_y<TT>)</TT><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>sqrt<CODE> </CODE><TT>(</TT><TT>(</TT>x<CODE>*.</CODE>x<TT>)</TT><CODE> </CODE><CODE>+.</CODE><CODE> </CODE><TT>(</TT>y<CODE>*.</CODE>y<TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR><CODE>val seg_length : interf_point -&gt; interf_point -&gt; float = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Interfaces can only mask fields of instance variables and private methods.
They cannot mask abstract or public methods.<BR>
<BR>
This is a restriction in their use, as shown by the following example:


<PRE><BR># <B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>new</B><CODE> </CODE>point_m1<CODE> </CODE><TT>(</TT><CODE>2</CODE><CODE>,</CODE><CODE>3</CODE><TT>)</TT><CODE> </CODE><CODE>:</CODE><CODE> </CODE>interf_point<TT>)</TT>;;<BR><CODE>Characters 11-29:</CODE><BR><CODE>This expression has type</CODE><BR><CODE>  point_m1 =</CODE><BR><CODE>    &lt; distance : unit -&gt; float; get_x : int; get_y : int;</CODE><BR><CODE>      moveto : int * int -&gt; unit; rmoveto : int * int -&gt; unit;</CODE><BR><CODE>      to_string : unit -&gt; string; undo : unit -&gt; unit &gt;</CODE><BR><CODE>but is here used with type</CODE><BR><CODE>  interf_point =</CODE><BR><CODE>    &lt; distance : unit -&gt; float; get_x : int; get_y : int;</CODE><BR><CODE>      moveto : int * int -&gt; unit; rmoveto : int * int -&gt; unit;</CODE><BR><CODE>      to_string : unit -&gt; string &gt;</CODE><BR><CODE>Only the first object type has a method undo</CODE><BR>

</PRE>
<BR>
<BR>
Nevertheless, interfaces may use inheritance. 
Interfaces are especially useful in combination with modules:
it is possible to build the signature of a module using
object types, while only making available the description of class interfaces.<BR>
<BR>
<A NAME="toc216"></A>
<H3> Local Declarations in Classes</H3>
<A NAME="@concepts337"></A>
A class declaration produces a type and a constructor. In order to
make this chapter easier to read, we have been presenting constructors as functions
without an environment. In fact, it is possible to define constructors which
do not need initial values to create an instance: that means that they are no
longer functional. Furthermore one can use local declarations in the
class. Local variables captured by the constructor are shared and can
be treated as class variables.<BR>
<BR>

<H4> Constant Constructors</H4>A class declaration does not need to use initial values passed to the
constructor. For example, in the following class: 


<PRE><BR># <B>class</B><CODE> </CODE>example1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>print<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class example1 : object method print : unit -&gt; unit end</CODE><BR># <B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>example1<CODE> </CODE>;;<BR><CODE>val p : example1 = &lt;obj&gt;</CODE><BR>

</PRE>

The instance constructor is constant. The allocation does not require an
initial value for the instance variables. As a rule, it is better to use an
initial value such as <TT>()</TT>, in order to preserve the functional nature
of the constructor.<BR>
<BR>

<H4> Local Declarations for Constructors</H4>
A local declaration can be written directly with abstraction. 


<PRE><BR># <B>class</B><CODE> </CODE>example2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>fun</B><CODE> </CODE>a<CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>a<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>plus<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r<CODE> </CODE><CODE>+</CODE><CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR><CODE>class example2 :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object val mutable r : int method get_r : int method plus : int -&gt; unit end</CODE><BR>

</PRE>
<BR>
<BR>
Here it is easier to see the functional nature of the constructor. The
constructor is a closure which may have an environment that binds free variables
to an environment of declarations. The syntax for class declarations allows
local declarations in this functional expression.<BR>
<BR>

<H4> Class Variables</H4>
<A NAME="@concepts338"></A>
Class variables are declarations which are known at class level and therefore
shared by all instances of the class. Usually these class variables can be
used outside of any instance creation. 
In Objective CAML, thanks to the functional nature of a constructor with a non-empty 
environment, we can make these
values (particularly the modifiable ones) shared by all instances of a class.<BR>
<BR>
We illustrate this facility with the following example, which allows us to
keep a register of the number of instances of a class. To do this we
define a parameterized abstract class <I>'a om</I>.


<PRE><BR># <B>class</B><CODE> </CODE><B>virtual</B><CODE> </CODE><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>om<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><CODE> </CODE>finalize<CODE> </CODE>()<CODE> </CODE><CODE> </CODE><CODE>=</CODE><CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>destroy<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>to_string<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>string<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>virtual</B><CODE> </CODE>all<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>list<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR>

</PRE>
<BR>
<BR>
Then we declare class <TT>'a lo</TT>, whose constructor contains
local declarations for <TT>n</TT>, which associates a unique number with each
instance, and for <TT>l</TT>, which contains the list of pairs (number,
instance) of still active instances.


<PRE><BR># <B>class</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>lo<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE>[]<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>fun</B><CODE> </CODE>s<CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><TT>(</TT>self<CODE>:</CODE><I>'b</I><CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE><I>'a</I><CODE>]</CODE><CODE> </CODE>om<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>num<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>name<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>to_string<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>print<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE>s<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>print_all<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>List.iter<CODE> </CODE><TT>(</TT><B>function</B><CODE> </CODE><TT>(</TT>a<CODE>,</CODE>b<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"(%d,%s) "</CODE><CODE> </CODE>a<CODE> </CODE><TT>(</TT>b#to_string()<TT>)</TT><TT>)</TT><CODE> </CODE><CODE>!</CODE>l<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>destroy<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>self#finalize();<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>l<CODE>:=</CODE><CODE> </CODE>List.filter<CODE> </CODE><TT>(</TT><B>function</B><CODE> </CODE><TT>(</TT>a<CODE>,</CODE>b<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE>a<CODE> </CODE><CODE>&lt;&gt;</CODE><CODE> </CODE>num<TT>)</TT><CODE> </CODE><CODE>!</CODE>l;<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>all<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.map<CODE> </CODE>snd<CODE> </CODE><CODE>!</CODE>l<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>initializer</B><CODE> </CODE>incr<CODE> </CODE>n;<CODE> </CODE>num<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>!</CODE>n;<CODE> </CODE><CODE> </CODE>l<CODE>:=</CODE><CODE> </CODE><TT>(</TT>num<CODE>,</CODE><CODE> </CODE><TT>(</TT>self<CODE> </CODE><CODE>:&gt;</CODE><CODE> </CODE><I>'a</I><CODE> </CODE><CODE> </CODE>om<TT>)</TT><CODE> </CODE><TT>)</TT><CODE> </CODE>::<CODE> </CODE><CODE>!</CODE>l<CODE> </CODE>;<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<CODE> </CODE><BR><CODE>class ['a] lo :</CODE><BR><CODE>  string -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    constraint 'a = 'a om</CODE><BR><CODE>    val name : string</CODE><BR><CODE>    val mutable num : int</CODE><BR><CODE>    method all : 'a list</CODE><BR><CODE>    method destroy : unit -&gt; unit</CODE><BR><CODE>    method finalize : unit -&gt; unit</CODE><BR><CODE>    method print : unit -&gt; unit</CODE><BR><CODE>    method print_all : unit -&gt; unit</CODE><BR><CODE>    method to_string : unit -&gt; string</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
At each creation of an instance of class <I>lo</I>, the initializer
increments the reference <TT>n</TT> and adds the pair (number, <TT>self</TT>)
to the list <TT>l</TT>. Methods <TT>print</TT> and <TT>print_all</TT> display
respectively the receiving instance and all the instances containing in <TT>l</TT>. <BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>m1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>lo<CODE> </CODE><CODE>"start"</CODE>;;<BR><CODE>val m1 : ('a om as 'a) lo = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>m2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>lo<CODE> </CODE><CODE>"between"</CODE>;;<BR><CODE>val m2 : ('a om as 'a) lo = &lt;obj&gt;</CODE><BR># <B>let</B><CODE> </CODE>m3<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>lo<CODE> </CODE><CODE>"end"</CODE>;;<BR><CODE>val m3 : ('a om as 'a) lo = &lt;obj&gt;</CODE><BR># m2#print_all();;<BR><CODE>(3,end) (2,between) (1,start) - : unit = ()</CODE><BR># m2#all;;<BR><CODE>- : ('a om as 'a) list = [&lt;obj&gt;; &lt;obj&gt;; &lt;obj&gt;]</CODE><BR>

</PRE>
<BR>
<BR>
Method <TT>destroy</TT> removes an instance from the list of instances, and
calls method <TT>finalize</TT> to perform a last action on this instance before
it disappears from the list. Method <TT>all</TT> returns all the instances of a
class created with <B>new</B>.


<PRE><BR># m2#destroy();;<BR><CODE>- : unit = ()</CODE><BR># m1#print_all();;<BR><CODE>(3,end) (1,start) - : unit = ()</CODE><BR># m3#all;;<BR><CODE>- : ('a om as 'a) list = [&lt;obj&gt;; &lt;obj&gt;]</CODE><BR>

</PRE>
<BR>
<BR>
We should note that instances of subclasses are also kept in this list. Nothing
prevents you from using the same technique by specializing some of these subclasses.
On the other hand, the instances obtained by a copy (<TT>Oo.copy</TT> or
<B>{&lt; &gt;}</B>) are not tracked.<BR>
<BR>
<BR>
<BR>

<BR>
<BR>
<HR>
<A HREF="book-ora145.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora147.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
